# !/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time    : 2019/8/19 14:15
# @Author  : LiHaowen
# @Email   : lihaowen2017@163.com
from django.urls import reverse_lazy
# django 的消息机制
from django.contrib import messages
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView, ListView, UpdateView, DetailView
from django_comments.signals import comment_was_posted  # 导入django-comment信号量
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page

from web_ask.articles.models import Article
from web_ask.articles.forms import ArticleForm
from web_ask.helpers import AuthorRequireMixin
from web_ask.notifications.views import notification_handler


class ArticlesListView(LoginRequiredMixin, ListView):
    """已发布的文章列表"""
    model = Article
    paginate_by = 10
    context_object_name = "articles"
    template_name = "articles/article_list.html"

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super().get_context_data()
        context['popular_tags'] = Article.objects.get_counted_tags()
        return context

    def get_queryset(self):
        return Article.objects.get_published()


class DraftListView(ArticlesListView):
    """草稿箱文章列表"""
    def get_queryset(self):
        """当前的用户的草稿"""
        return Article.objects.filter(user=self.request.user).get_drafts()


@method_decorator(cache_page(60*60), name="get")  # 缓存get方法1小时，get只能小写
class ArticleCreateView(LoginRequiredMixin, CreateView):
    """发表文章"""
    model = Article
    form_class = ArticleForm
    template_name = "articles/article_create.html"
    message = "您的文章已创建成功！"
    # initial = {'title': 'ok'}  # 初始值填充，实现效果，创建文章时，标题内容自动填充ok

    def form_valid(self, form):
        """登录的用户传递给表单实例;表单验证通过，将数据关联到对应模型字段中"""
        form.instance.user = self.request.user
        return super().form_valid(form)  # 加载父类方法返回

    def get_success_url(self):
        """创建成功后跳转"""
        # messages 是消息机制框架，message为自定义字符串， 成功创建的消息传递给下次请求
        # 消息机制是需要将某消息传递给下一次请求，到再下一次请求时，消息消失
        # 信号量机制属于触发机制与是否为下一次请求无关
        messages.success(self.request, self.message)
        return reverse_lazy("articles:list")

    # def get_initial(self):
    #     """动态初始值填充效果，pass中填写相关逻辑，应用场景有规律的发送一些固定消息，如定时公告"""
    #     initial = super().get_initial()
    #     pass
    #     return initial


class ArticleDetailView(LoginRequiredMixin, DetailView):
    """文章详情"""
    model = Article
    template_name = "articles/article_detail.html"

    def get_queryset(self):
        """文章详情中同样存在用户信息，需要优化sql"""
        return Article.objects.select_related('user').filter(slug=self.kwargs['slug'])  # self.kwargs['slug']获取url参数


# 类的继承顺序
class ArticleEditView(LoginRequiredMixin, AuthorRequireMixin, UpdateView):
    """编辑文章"""
    model = Article
    message = "您的文章编辑成功"
    form_class = ArticleForm
    template_name = "articles/article_update.html"

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super().form_valid(form)  # 加载父类方法返回

    def get_success_url(self):
        """编辑成功后跳转"""
        messages.success(self.request, self.message)  # 消息传递给下一次请求
        #  使用字典传参
        return reverse_lazy("articles:article", kwargs={"slug": self.get_object().slug})


def notify_comment(**kwargs):
    """文章有评论时通知作者"""
    actor = kwargs["request"].user
    # comment获取django-comment模型类(通用模型类)实例 content_object使用content_type关联到任意模型类
    obj = kwargs["comment"].content_object
    notification_handler(actor, obj.user, "C", obj)


# 观察者模式 = 订阅[列表] + 通知（同步）
comment_was_posted.connect(receiver=notify_comment)  # receiver 信号的目标，评论被提交后执行的函数
